package com.tacorpus.ui.wizards;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceStatus;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.actions.WorkspaceModifyOperation;
import org.eclipse.ui.dialogs.WizardNewProjectCreationPage;
import org.eclipse.ui.wizards.newresource.BasicNewResourceWizard;

import com.tacorpus.ui.Activator;

public class TacorpusProjectNewWizard extends BasicNewResourceWizard {

	private WizardNewProjectCreationPage besicProjectPage;
	private TacorpusProjectWizardPage tacorpusProjectPage;

	private IProject newProject;

	public TacorpusProjectNewWizard() {
		super();
	}

	public void init(IWorkbench workbench, IStructuredSelection currentSelection) {
		super.init(workbench, currentSelection);
		setNeedsProgressMonitor(true);
		setWindowTitle("New Tacorpus Project Wizard");
	}

	public void addPages() {
		besicProjectPage = new WizardNewProjectCreationPage(
				"New Tacorpus Project Wizard");
		besicProjectPage.setTitle("New Tacorpus Project Wizard");
		besicProjectPage.setDescription("New Tacorpus Project Wizard");
		this.addPage(besicProjectPage);

		tacorpusProjectPage = new TacorpusProjectWizardPage();
		this.addPage(tacorpusProjectPage);
	}

	private IProject createNewProject() {
		if (newProject != null) {
			return newProject;
		}

		// get a project handle
		final IProject newProjectHandle = besicProjectPage.getProjectHandle();

		// get a project descriptor
		URI location = null;
		if (!besicProjectPage.useDefaults()) {
			location = besicProjectPage.getLocationURI();
		}

		IWorkspace workspace = ResourcesPlugin.getWorkspace();
		final IProjectDescription description = workspace
				.newProjectDescription(newProjectHandle.getName());
		description.setLocationURI(location);

		// create the new project operation
		WorkspaceModifyOperation op = new WorkspaceModifyOperation() {
			protected void execute(IProgressMonitor monitor)
					throws CoreException {
				createProject(description, newProjectHandle, monitor);
			}
		};

		// run the new project creation operation
		try {
			getContainer().run(true, true, op);
		} catch (InterruptedException e) {
			return null;
		} catch (InvocationTargetException e) {
			// ie.- one of the steps resulted in a core exception
			Throwable t = e.getTargetException();
			if (t instanceof CoreException) {
				if (((CoreException) t).getStatus().getCode() == IResourceStatus.CASE_VARIANT_EXISTS) {
					MessageDialog.openError(getShell(), "プロジェクトの生成に失敗しました",
							"プロジェクトの生成に失敗しました");
				} else {
					ErrorDialog.openError(getShell(), "プロジェクトの生成に失敗しました", null, // no
							// special
							// message
							((CoreException) t).getStatus());
				}
			} else {
				// CoreExceptions are handled above, but unexpected runtime
				// exceptions and errors may still occur.
				Activator.getDefault().getLog().log(
						new Status(IStatus.ERROR, Activator.PLUGIN_ID, 0, t
								.toString(), t));
				MessageDialog.openError(getShell(), "プロジェクトの生成に失敗しました", t
						.getMessage());
			}
			return null;
		}
		newProject = newProjectHandle;

		return newProject;
	}

	void createProject(IProjectDescription description, IProject projectHandle,
			IProgressMonitor monitor) throws CoreException,
			OperationCanceledException {
		try {
			monitor.beginTask("", 2000);//$NON-NLS-1$

			projectHandle.create(description, new SubProgressMonitor(monitor,
					1000));

			if (monitor.isCanceled()) {
				throw new OperationCanceledException();
			}

			projectHandle.open(IResource.BACKGROUND_REFRESH,
					new SubProgressMonitor(monitor, 1000));

		} finally {
			monitor.done();
		}
	}

	@Override
	public boolean performFinish() {
		createNewProject();

		if (newProject == null) {
			return false;
		}

		//TODO: プロジェクト設定ファイルの出力（仕様未定）
		boolean errorFlag = false;
		IFile file = newProject.getFile("config.txt");
		String contents = tacorpusProjectPage
				.getTranslationComboSelectionIndex()
				+ ":" + tacorpusProjectPage.getTranslationComboSelectionLabel();
		InputStream stream = new ByteArrayInputStream(contents.getBytes());
		try {
			file.create(stream, false, null);
		} catch (CoreException e) {
			Activator.getDefault().getLog().log(
					new Status(IStatus.ERROR, Activator.PLUGIN_ID, 0, e
							.toString(), e));
			MessageDialog.openError(getShell(), "設定ファイルの生成に失敗しました。", e
					.getMessage());
			errorFlag = true;
		}
		try {
			stream.close();
		} catch (IOException e) {
			Activator.getDefault().getLog().log(
					new Status(IStatus.ERROR, Activator.PLUGIN_ID, 0, e
							.toString(), e));
		}
		if(errorFlag) {
			return false;
		}

		selectAndReveal(newProject);

		return true;
	}	

}